// ClientCal.cc
#include <time.h>
#include <unistd.h>
#include "TcpSocket.hpp"
#include "Protocol.hpp"

void Usage(const std::string &proc)
{
    std::cout << "\n\rUsage: " << proc << " serverip serverport\n"
              << std::endl;
}

// ./clientcal ip port
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(UsageErr);
    }
    std::string serverip = argv[1];
    uint16_t serverport = std::stoi(argv[2]);

    TcpSocket sock;
    sock.Socket();
    bool r = sock.Connect(serverip, serverport);
    if (!r) return 1;

    int cnt = 5;
    srand(time(nullptr) ^ getpid());
    const std::string opers = "+-*/%=^&";
    std::string inbuffer_stream;
    while(cnt--)
    {
        std::cout << "===============第" << 5 - cnt << "次测试...===============" << std::endl;
        int x = rand() % 100;
        usleep(1234);
        int y = rand() % 100;
        usleep(4321);
        char oper = opers[rand() % opers.size()];
        Request req(x, y, oper);
        req.DebugPrint();

        std::string package;
        req.Serialize(&package);
        package = Encode(package);

        std::cout << "完整报文：" << package;

        write(sock.getfd(), package.c_str(), package.size());
        // write(sock.getfd(), package.c_str(), package.size());
        // write(sock.getfd(), package.c_str(), package.size());
        // write(sock.getfd(), package.c_str(), package.size());
        // write(sock.getfd(), package.c_str(), package.size());

        char buffer[1280];
        ssize_t n = read(sock.getfd(), buffer, sizeof(buffer));  // 无法保证能读到一个完整的报文
        if (n > 0)
        {
            buffer[n] = 0;
            inbuffer_stream += buffer;  // "len"\n"result code"\n
            std::string content;
            bool r = Decode(inbuffer_stream, &content);  // "result code"
            if (!r) continue;

            Response resp;
            resp.Deserialize(content);
            if (!r) continue;
            resp.DebugPrint();
        }
        sleep(1);
    }
    
    sock.Close();
    return 0;
}